import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
#step1.读取数据，并不设置行索引和列索引
data = pd.read_csv("points.txt", sep=",",index_col=False, header=None)
data = data.values

#由效果图可知，这些数据共分成8类，k=8，若没有给出最后结果，那么要花出去散点图去判断，又或者用一些优化方法去解决。
#下面是em算法解决k-means聚类的过程
#step1.随机化u1,u2,....u8（一种方法：打乱所有数据，选择打乱后前8个数据做初始的样本中心
#step2.e——step：更新点的情况，看点分属哪一类
#step3. m——step 更新样本中心
#step4.不断循环此过程，直至收敛
K = 8
centers = data[np.random.choice(range(len(data)), K, replace=False)]

# 初始化变量以便检查收敛性
last_assignments = None
i_max = 10000
#增加计数器,限制最大次数
for i in range(i_max):

    # E步骤：根据到中心点的距离将点分配到聚类中
    distances = np.sqrt(((data - centers[:, np.newaxis]) ** 2).sum(axis=2))
    assignments = np.argmin(distances, axis=0)

    # 检查收敛性
    if np.array_equal(assignments, last_assignments):
        print(f"在{i}次迭代后收敛")
        break

    # M步骤：根据新的聚类分配更新聚类中心
    for j in range(K):
        centers[j] = np.mean(data[assignments == j], axis=0)

    last_assignments = assignments.copy()

print("最终的聚类中心:", centers)
A = ['r','y', 'g', 'b', 'k', 'w', 'c', 'm']
for j in range(K):
    C = A[j]
    plt.scatter(data[assignments == j, 0], data[assignments == j, 1],
                c=C)
#用于绘制的数据点是基于布尔数组assignments == j选择的，该数组对于等于j的assignments元素返回True，否则返回False

plt.show()
#注：这里不一定能获得最优解，要多做几次才行
